package cn.elane.elastic.global.jdbc;

import com.mysql.cj.util.StringUtils;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Chenyu
 * @date 2020-3-20
 */
public class JdbcSource {

	private final static String DEFAULT_ALIAS = "default";

	/**
	 * 数据源
	 */
	private static Map<String, DataSource> dataSourceMap;

	static {
		dataSourceMap = new HashMap<>();
	}

	public static boolean addDataSource(String alias, DataSource dataSource) {
		if (alias == null || "".equals(alias)) {
			return false;
		}
		//TODO: 已存在不可直接覆盖,需要停止之前的数据源后,添加新的数据源!
		if (dataSourceMap.containsKey(alias)) {
			return false;
		}
		dataSourceMap.put(alias, dataSource);
		return true;
	}

	/**
	 * 检查数据源是否存在
	 *
	 * @param alias 数据源名称
	 * @return
	 */
	public static boolean checkAlias(String alias) {
		if (StringUtils.isNullOrEmpty(alias)) {
			return false;
		}
		if (!dataSourceMap.containsKey(alias) || dataSourceMap.get(alias) == null) {
			System.err.println("数据源【" + alias + "】不存在！");
			return false;
		}
		return true;
	}

	/**
	 * 获取默认连接池的连接.
	 *
	 * @return Connection
	 */
	public static Connection getConnection() {
		return getConnection(null);
	}

	/**
	 * 指定连接池获取连接.
	 *
	 * @param alias 指定数据源
	 * @return Connection
	 */
	public static Connection getConnection(String alias) {
		try {
			if (StringUtils.isNullOrEmpty(alias)) {
				alias = DEFAULT_ALIAS;
			}
			DataSource dataSource = dataSourceMap.get(alias);
			if (dataSource != null) {
				return dataSource.getConnection();
			}
			System.out.println("数据源:" + alias + "不存在！");
			return null;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 初始化数据源.
	 */
//	public static void initDataSources() {
//		if (dataSourceMap == null || dataSourceMap.isEmpty() || dataSourceMap.get(DEFAULT_ALIAS) == null) {
//			System.err.println("默认数据源异常！");
//			throw new RuntimeException("默认数据源异常！");
//		}
//
//		Dao dao = new Dao();
//		List<NameBean> dbs = dao.findList(XqlLoader.load("load_dataSource"));
//		System.out.println(NameBeanUtil.toJson(dbs));
//		String url = "";
//		for (NameBean db : dbs) {
//			DruidDataSource dataSource = new DruidDataSource();
//			dataSource.setUsername(db.str("username"));
//			dataSource.setPassword(db.str("password"));
//
//			dataSource.setDbType(db.str("type"));
//			switch (db.str("type")) {
//				case JdbcConstants.MYSQL:
//					if (!db.str("driverClass").equals(JdbcConstants.MYSQL_DRIVER) && !db.str("driverClass").equals(JdbcConstants.MYSQL_DRIVER_6)) {
//						throw new RuntimeException("数据源:" + db.str("name") + "驱动异常！");
//					}
//					url = "jdbc:mysql://" +
//							db.str("address") +
//							":" +
//							db.str("port") +
//							"/" +
//							db.str("dbName") +
//							"?useSSL=false&serverTimezone=Hongkong&useUnicode=true&characterEncoding=utf8";
//					break;
//				case JdbcConstants.SQL_SERVER:
//					if (!db.str("driverClass").equals(JdbcConstants.SQL_SERVER_DRIVER) && !db.str("driverClass").equals(JdbcConstants.SQL_SERVER_DRIVER_SQLJDBC4)) {
//						throw new RuntimeException("数据源:" + db.str("name") + "驱动异常！");
//					}
//					url = "jdbc:sqlserver://" +
//							db.str("address") +
//							":" +
//							db.str("port") +
//							";DatabaseName=" +
//							db.str("dbName");
//					break;
//				case JdbcConstants.ORACLE:
//					if (!db.str("driverClass").equals(JdbcConstants.ORACLE_DRIVER) && !db.str("driverClass").equals(JdbcConstants.ORACLE_DRIVER2)) {
//						throw new RuntimeException("数据源:" + db.str("name") + "驱动异常！");
//					}
//					url = "jdbc:oracle:thin:@" +
//							db.str("address") +
//							":" +
//							db.str("port") +
//							":" +
//							db.str("dbName");
//					break;
//				case JdbcConstants.ALI_ORACLE:
//					throw new RuntimeException("暂不支持AliOracle！");
//                    /*if (!db.str("driverClass").equals(JdbcConstants.ALI_ORACLE_DRIVER)) {
//                        throw new RuntimeException("数据源:" + db.str("name") + "驱动异常！");
//                    }*/
//				case JdbcConstants.POSTGRESQL:
//					if (!db.str("driverClass").equals(JdbcConstants.POSTGRESQL_DRIVER)) {
//						throw new RuntimeException("数据源:" + db.str("name") + "驱动异常！");
//					}
//					url = "jdbc:postgresql://" +
//							db.str("address") +
//							":" +
//							db.str("port") +
//							"/" +
//							db.str("dbName");
//					break;
//				default:
//			}
//			if ("".equals(url)) {
//				throw new RuntimeException("数据源:" + db.str("name") + "异常！");
//			}
//			dataSource.setUrl(url);
//			dataSource.setDriverClassName(db.str("driverClass"));
//			addDataSource(db.str("uuid"), dataSource);
//		}
//		log();
//	}

	public static void log() {
		System.out.println("-------------------------------------------------------------------");
		System.out.println("--------------------------JDBCSource Log.--------------------------");
		System.out.println(dataSourceMap);
		System.out.println("-------------------------------------------------------------------");
		System.out.println("-------------------------------------------------------------------");
	}

	public static String getDefaultAlias() {
		return DEFAULT_ALIAS;
	}

	/**
	 * 关闭ResultSet
	 *
	 * @param resultSet ResultSet
	 */
	public static void close(ResultSet resultSet) {
		try {
			if (resultSet != null && !resultSet.isClosed()) {
				resultSet.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 关闭Statement
	 *
	 * @param statement Statement
	 */
	public static void close(Statement statement) {
		try {
			if (statement != null && !statement.isClosed()) {
				statement.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 关闭Connection
	 *
	 * @param connection Connection
	 */
	public static void close(Connection connection) {
		try {
			if (connection != null && !connection.isClosed()) {
				connection.close();
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 依次关闭ResultSet、Statement和Connection
	 *
	 * @param connection 3
	 * @param statement  2
	 * @param resultSet  1
	 */
	public static void close(Connection connection, Statement statement, ResultSet resultSet) {
		close(resultSet);
		close(statement);
		close(connection);
	}
}
